package com.wfm.limitalgor;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;
 // https://mp.weixin.qq.com/s/A5VYjstIDeVvizNK2HkrTQ
@Slf4j
public class FixedWindowRateLimiter {
    //时间窗口大小，单位毫秒
    long windowSize;
    //允许通过的请求数
    int maxRequestCount;
    //当前窗口通过的请求数
    AtomicInteger counter = new AtomicInteger(0);
    //窗口右边界
    long windowBorder;
    public FixedWindowRateLimiter(long windowSize, int maxRequestCount) {
        this.windowSize = windowSize;
        this.maxRequestCount = maxRequestCount;
        this.windowBorder = System.currentTimeMillis() + windowSize;
    }
    public synchronized boolean tryAcquire() {
        long currentTime = System.currentTimeMillis();
        if (windowBorder < currentTime) {
            log.info("window reset");
            do {
                windowBorder += windowSize;
            } while (windowBorder < currentTime);
            counter = new AtomicInteger(0);
        }

        if (counter.intValue() < maxRequestCount) {
            counter.incrementAndGet();
            log.info("tryAcquire success");
            return true;
        } else {
            log.info("tryAcquire fail");
            return false;
        }
    }

     public static void main(String[] args) throws InterruptedException {
         test2();
     }

     /**
      * 0__1__2__3
      */
     private static void test1() throws InterruptedException {
         FixedWindowRateLimiter limiter = new FixedWindowRateLimiter(1000, 3);
         for (int i = 0; i < 4; i++) {
             System.out.println("================="+i+"=============");
             switch (i){
                 case 0:
                     for (int j = 0; j < 3; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 case 1:
                     for (int j = 0; j < 4; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 case 2:
                     for (int j = 0; j < 5; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 case 3:
                     for (int j = 0; j < 2; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 default:
                     break;
             }

             Thread.sleep(1000);

         }
     }

     /**
      * 总共4个0.5s，就是2s
      * 第一个0.5s：不请求
      * 第二个0.5s: 请求3个
      * 第三个0.5s：请求3个
      * 第四个0.5s：不请求
      * 结果是中间这1s通过了6个
      *
      */
     private static void test2() throws InterruptedException {
         FixedWindowRateLimiter limiter = new FixedWindowRateLimiter(1000, 3);
         for (int i = 0; i < 6; i++) {
             System.out.println("================="+i+"=============");
             switch (i){
                 case 0:
                     break;
                 case 1:
                     for (int j = 0; j < 3; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 case 5:
                     for (int j = 0; j < 6; j++) {
                         limiter.tryAcquire();
                     }
                     break;
                 default:
                     break;
             }

             Thread.sleep(500);

         }
     }


 }